import { EventEmitter } from 'events';
import { v4 as uuidv4 } from 'uuid';
import chalk from 'chalk';
import { SSHManager } from './ssh-manager';
import { DeepSeekClient } from './deepseek-client';
import { AutomationTask, CommandResult, SSHConfig, DeepSeekConfig } from '../types';
import { logger } from '../utils/logger';

export class AutomationEngine extends EventEmitter {
  private sshManager: SSHManager;
  private deepseekClient: DeepSeekClient;
  private tasks: Map<string, AutomationTask> = new Map();
  private currentSessionId: string | null = null;

  constructor(sshConfig: SSHConfig, deepseekConfig: DeepSeekConfig) {
    super();
    this.sshManager = new SSHManager();
    this.deepseekClient = new DeepSeekClient(deepseekConfig);

    this.sshManager.on('connected', (sessionId) => {
      this.emit('ssh-connected', sessionId);
    });

    this.sshManager.on('disconnected', (sessionId) => {
      this.emit('ssh-disconnected', sessionId);
    });

    this.sshManager.on('error', (sessionId, error) => {
      this.emit('ssh-error', sessionId, error);
    });
  }

  async initializeSSHConnection(sshConfig: SSHConfig): Promise<string> {
    const sessionId = uuidv4();

    try {
      await this.sshManager.connect(sessionId, sshConfig);
      this.currentSessionId = sessionId;
      logger.info(`SSH会话已建立: ${sessionId}`);
      return sessionId;
    } catch (error) {
      logger.error(`SSH连接失败: ${error}`);
      throw error;
    }
  }

  async executeAutomatedTask(taskDescription: string): Promise<AutomationTask> {
    if (!this.currentSessionId) {
      throw new Error('未建立SSH连接');
    }

    const taskId = uuidv4();
    const task: AutomationTask = {
      id: taskId,
      description: taskDescription,
      commands: [],
      status: 'pending',
      results: [],
      createdAt: new Date()
    };

    this.tasks.set(taskId, task);
    this.emit('task-created', task);

    try {
      logger.info(`开始执行自动化任务: ${taskDescription}`);
      task.status = 'running';
      this.tasks.set(taskId, task);
      this.emit('task-updated', task);

      const systemInfo = await this.deepseekClient.getSystemInfo(
        this.currentSessionId,
        this.sshManager
      );

      const deepseekResponse = await this.deepseekClient.analyzeTask(
        taskDescription,
        systemInfo
      );

      if (!deepseekResponse.commands || deepseekResponse.commands.length === 0) {
        throw new Error('DeepSeek未生成有效命令');
      }

      task.commands = deepseekResponse.commands;
      this.tasks.set(taskId, task);
      this.emit('task-updated', task);

      logger.info(`DeepSeek生成了 ${task.commands.length} 个命令`);
      logger.info(`执行分析: ${deepseekResponse.reasoning}`);

      // 显示即将执行的命令
      console.log(chalk.cyan('\n💻 即将执行的命令:'));
      task.commands.forEach((cmd, index) => {
        console.log(chalk.white(`  ${index + 1}. ${cmd}`));
      });
      console.log(chalk.yellow('\n⚡ 开始执行...\n'));

      const commandResults = await this.sshManager.executeMultipleCommands(
        this.currentSessionId,
        task.commands
      );

      task.results = commandResults;

      const allSuccessful = commandResults.every(result => result.success);

      if (allSuccessful) {
        task.status = 'completed';
        task.completedAt = new Date();
        logger.info(`任务执行成功: ${taskDescription}`);
      } else {
        task.status = 'failed';
        logger.warn(`任务执行失败: ${taskDescription}`);

        const analysisResponse = await this.deepseekClient.analyzeResults(
          taskDescription,
          commandResults
        );

        logger.info(`错误分析: ${analysisResponse.reasoning}`);

        if (analysisResponse.commands && analysisResponse.commands.length > 0) {
          logger.info('DeepSeek建议执行额外修复命令');
          task.commands.push(...analysisResponse.commands);

          const additionalResults = await this.sshManager.executeMultipleCommands(
            this.currentSessionId,
            analysisResponse.commands
          );

          task.results.push(...additionalResults);

          const allFixed = additionalResults.every(result => result.success);
          if (allFixed) {
            task.status = 'completed';
            task.completedAt = new Date();
            logger.info('修复命令执行成功，任务已完成');
          }
        }
      }

      this.tasks.set(taskId, task);
      this.emit('task-updated', task);

      if (task.status === 'completed') {
        this.emit('task-completed', task);
      } else {
        this.emit('task-failed', task);
      }

      return task;

    } catch (error) {
      logger.error(`自动化任务执行失败: ${error}`);
      task.status = 'failed';
      task.completedAt = new Date();
      this.tasks.set(taskId, task);
      this.emit('task-failed', task);
      throw error;
    }
  }

  async executeInteractiveTask(taskDescription: string): Promise<{
    claudeResponse: any;
    taskId: string;
  }> {
    if (!this.currentSessionId) {
      throw new Error('未建立SSH连接');
    }

    const taskId = uuidv4();
    const task: AutomationTask = {
      id: taskId,
      description: taskDescription,
      commands: [],
      status: 'pending',
      results: [],
      createdAt: new Date()
    };

    this.tasks.set(taskId, task);

    try {
      logger.info(`分析交互式任务: ${taskDescription}`);

      const systemInfo = await this.deepseekClient.getSystemInfo(
        this.currentSessionId,
        this.sshManager
      );

      const deepseekResponse = await this.deepseekClient.analyzeTask(
        taskDescription,
        systemInfo
      );

      task.commands = deepseekResponse.commands || [];
      this.tasks.set(taskId, task);

      return { claudeResponse: deepseekResponse, taskId };

    } catch (error) {
      logger.error(`交互式任务分析失败: ${error}`);
      task.status = 'failed';
      this.tasks.set(taskId, task);
      throw error;
    }
  }

  async executeCommands(taskId: string, commands: string[]): Promise<CommandResult[]> {
    if (!this.currentSessionId) {
      throw new Error('未建立SSH连接');
    }

    const task = this.tasks.get(taskId);
    if (!task) {
      throw new Error(`任务不存在: ${taskId}`);
    }

    try {
      task.status = 'running';
      task.commands = commands;
      this.tasks.set(taskId, task);
      this.emit('task-updated', task);

      const results = await this.sshManager.executeMultipleCommands(
        this.currentSessionId,
        commands
      );

      task.results = results;
      task.status = results.every(r => r.success) ? 'completed' : 'failed';
      task.completedAt = new Date();

      this.tasks.set(taskId, task);
      this.emit('task-updated', task);

      return results;

    } catch (error) {
      logger.error(`命令执行失败: ${error}`);
      task.status = 'failed';
      task.completedAt = new Date();
      this.tasks.set(taskId, task);
      this.emit('task-failed', task);
      throw error;
    }
  }

  async executeCustomCommand(command: string): Promise<CommandResult> {
    if (!this.currentSessionId) {
      throw new Error('未建立SSH连接');
    }

    logger.info(`执行自定义命令: ${command}`);
    return await this.sshManager.executeCommand(this.currentSessionId, command);
  }

  getTask(taskId: string): AutomationTask | undefined {
    return this.tasks.get(taskId);
  }

  getAllTasks(): AutomationTask[] {
    return Array.from(this.tasks.values());
  }

  getTasksByStatus(status: AutomationTask['status']): AutomationTask[] {
    return Array.from(this.tasks.values()).filter(task => task.status === status);
  }

  isConnected(): boolean {
    return this.currentSessionId !== null &&
           this.sshManager.isConnected(this.currentSessionId);
  }

  getCurrentSessionId(): string | null {
    return this.currentSessionId;
  }

  async disconnect(): Promise<void> {
    if (this.currentSessionId) {
      await this.sshManager.disconnect(this.currentSessionId);
      this.currentSessionId = null;
      logger.info('SSH连接已断开');
    }
  }

  async cleanup(): Promise<void> {
    await this.sshManager.disconnectAll();
    this.tasks.clear();
    this.currentSessionId = null;
    logger.info('自动化引擎已清理');
  }

  getConnectionStatus(): {
    connected: boolean;
    sessionId: string | null;
    sessionInfo?: any;
  } {
    if (!this.currentSessionId) {
      return { connected: false, sessionId: null };
    }

    const sessionInfo = this.sshManager.getSession(this.currentSessionId);
    return {
      connected: this.sshManager.isConnected(this.currentSessionId),
      sessionId: this.currentSessionId,
      sessionInfo
    };
  }

  startSessionCleanup(intervalMs: number = 300000): void {
    setInterval(() => {
      this.sshManager.cleanupInactiveSessions();
    }, intervalMs);
  }
}